package cn.edu.buu.hospital.advice;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import java.sql.Timestamp;
//散布在各处的公共代码集中放置到通知(增强)
@Aspect  // 添加这个注解，将类标记为切面类
@Component // 添加这个注解，让Spring能够扫描到这个组件
public class HisAdvice {
    // 修改pointCut方法，使其成为一个有效的切点表达式
    @Pointcut("execution(* cn.edu.buu.hospital.service..*.*(..))")
    public void pointCut(){}
    //前置通知
    @Before("pointCut()")
    public void before(JoinPoint joinPoint){
        Signature signature = joinPoint.getSignature();
        System.out.println("....."+signature.getName()+"方法(切入点)准备运行");
    }
    //后置通知
    @AfterReturning(value = "pointCut()", returning = "returnValue")
    public void afterReturn(JoinPoint joinPoint,Object returnValue){
        String methodName = joinPoint.getSignature().getName();
        System.out.println(".....方法(切入点)运行结束--得到返回值--"+returnValue+"---");
    }
    //异常通知
    @AfterThrowing(value = "pointCut()", throwing = "e")
    public void afterThrow(Throwable e){
        System.out.println(".....方法(切入点)运行中出现异常--打印异常轨迹------");
        System.out.println(e.getMessage()+"####################");
        e.printStackTrace();
        // 注意：在@AfterThrowing通知中，异常已经被抛出，不需要手动抛出
        // Spring会自动将异常传播给调用者，事务管理器会根据异常类型决定是否回滚
    }
    //最终通知，类似于finally，是否有异常都执行
    @After("pointCut()")
    public void finallyAdvice(JoinPoint joinPoint){
        String methodName = joinPoint.getSignature().getName();
        System.out.println("....."+methodName+"方法(切入点)运行完成****最终***");
    }
    //环绕通知
    @Around("pointCut()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        Object value;
        // 环绕通知开始（目标方法执行前）
        System.out.println("开始: " + new Timestamp(System.currentTimeMillis()));
        // 调用目标方法（切入点方法）
        value = proceedingJoinPoint.proceed();
        // 环绕通知结束（目标方法执行后）
        System.out.println("结束: " + new Timestamp(System.currentTimeMillis()));
        // 返回目标方法的返回值
        return value;
    }
}